import {
  App,
  Config,
  IMidwayApplication,
  Inject,
  Provide,
  Scope,
  ScopeEnum,
} from '@midwayjs/core';
import IORedis from 'ioredis';
import { TaskTopicEntity } from '../entity/topic';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { TaskTopicService } from './topic';
import { Queue, Worker } from 'bullmq';

/**
 * 初始化
 */
@Provide()
@Scope(ScopeEnum.Singleton, { allowDowngrade: true })
export class TaskInitService {
  redis;

  @Config('module.task.redis')
  redisConfig;

  @InjectEntityModel(TaskTopicEntity)
  taskTopicEntity: Repository<TaskTopicEntity>;

  @Inject()
  taskTopicService: TaskTopicService;

  @App()
  app: IMidwayApplication;

  async init() {
    // 初始化Queues
    this.app['QUEUES'] = {};
    // 初始化Workers
    this.app['WORKERS'] = {};
    // 初始化redis
    await this.ioRedis();
    // 初始化topic
    await this.topic();
  }

  /**
   * 获得连接
   * @returns
   */
  async getConnection() {
    return this.app['REDIS-CONNECTION'];
  }

  /**
   * 获得队列
   * @param appId
   * @param name
   * @returns
   */
  async getQueue(appId: number, name: string): Promise<Queue> {
    const key = `${appId}@${name}`;
    return this.app['QUEUES'][key];
  }

  /**
   * 获得队列
   * @param appId
   * @param name
   * @returns
   */
  async getWorker(appId: number, name: string): Promise<Worker> {
    const key = `${appId}@${name}`;
    return this.app['WORKERS'][key];
  }

  /**
   * topic
   */
  async topic() {
    // 重置所有
    await this.taskTopicEntity.update({}, { isInit: 0 });
    const list = await this.taskTopicEntity.findBy({ status: 1, isInit: 0 });
    for (const item of list) {
      await this.taskTopicService.create(item.id);
      await this.taskTopicEntity.update(item.id, { isInit: 1 });
    }
  }

  /**
   * redis
   */
  async ioRedis() {
    if (this.redisConfig instanceof Array) {
      this.redis = new IORedis.Cluster(this.redisConfig, {
        enableReadyCheck: false,
      });
    } else {
      this.redis = new IORedis({
        ...this.redisConfig,
        enableReadyCheck: false,
        maxRetriesPerRequest: null,
      });
    }
    this.app['REDIS-CONNECTION'] = this.redis;
  }
}
